package com.gun3y.entity.htmlparser;

import java.util.Locale;

import org.apache.commons.lang3.StringUtils;
import org.htmlparser.Attribute;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Tag;

import com.gun3y.entity.pattern.ExpressionType;

public class HasAttributeExFilter implements NodeFilter {

    private static final long serialVersionUID = 813810932195228313L;

    /**
     * The attribute to check for.
     */
    protected String mAttribute;

    /**
     * The value to check for.
     */
    protected String mValue;

    /**
     * The expression to check for
     */
    protected ExpressionType mExpression;

    /**
     * Creates a new instance of HasAttributeFilter. With no attribute name,
     * this would always return <code>false</code> from {@link #accept}.
     */
    public HasAttributeExFilter() {
	this("", null, ExpressionType.ExactMatch);
    }

    /**
     * Creates a new instance of HasAttributeFilter that accepts tags with the
     * given attribute.
     * 
     * @param attribute
     *            The attribute to search for.
     */
    public HasAttributeExFilter(String attribute) {
	this(attribute, null, ExpressionType.ExactMatch);
    }

    /**
     * Creates a new instance of HasAttributeFilter that accepts tags with the
     * given attribute and value.
     * 
     * @param attribute
     *            The attribute to search for.
     * @param value
     *            The value that must be matched, or null if any value will
     *            match.
     */
    public HasAttributeExFilter(String attribute, String value, ExpressionType expressionType) {
	mAttribute = attribute == null ? "" : attribute.toUpperCase(Locale.ENGLISH);
	mValue = value;
	mExpression = expressionType;

	if (mExpression == null) {
	    mExpression = ExpressionType.ExactMatch;
	}
    }

    /**
     * Get the attribute name.
     * 
     * @return Returns the name of the attribute that is acceptable.
     */
    public String getAttributeName() {
	return mAttribute;
    }

    /**
     * Set the attribute name.
     * 
     * @param name
     *            The name of the attribute to accept.
     */
    public void setAttributeName(String name) {
	mAttribute = name;
    }

    /**
     * Get the attribute value.
     * 
     * @return Returns the value of the attribute that is acceptable.
     */
    public String getAttributeValue() {
	return mValue;
    }

    /**
     * Set the attribute value.
     * 
     * @param value
     *            The value of the attribute to accept. If <code>null</code>,
     *            any tag with the attribute, no matter what it's value is
     *            acceptable.
     */
    public void setAttributeValue(String value) {
	mValue = value;
    }

    /**
     * Get the attribute expression.
     * 
     * @return Returns the expression of the attribute that is acceptable.
     */
    public ExpressionType getAttributeExpression() {
	return mExpression;
    }

    public void setAttributeExpression(ExpressionType mExpression) {
	this.mExpression = mExpression;
    }

    /**
     * Accept tags with a certain attribute.
     * 
     * @param node
     *            The node to check.
     * @return <code>true</code> if the node has the attribute (and value if
     *         that is being checked too), <code>false</code> otherwise.
     */
    public boolean accept(Node node) {
	boolean ret = false;

	if (node instanceof Tag) {
	    Tag tag = (Tag) node;
	    Attribute attribute = tag.getAttributeEx(mAttribute);

	    ret = null != attribute;

	    if (ret && StringUtils.isNotBlank(mValue) && StringUtils.isNotBlank(attribute.getValue())) {
		ret = this.mExpression.isValid(attribute.getValue(), mValue);
	    }
	}

	return ret;

    }
}
